﻿using Caliburn.Micro;
using MusicExplorer.Common;
using MusicExplorer.Data;
using MusicExplorer.Model;
using MusicExplorer.Repository;
using MusicExplorer.ViewModels.Wrappers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace MusicExplorer.ViewModels
{
    public sealed class HomePageViewModel : PageViewModelBase
    {
        private readonly BindableCollection<RepositoryTileViewModel> m_repositories;
        private readonly List<CategoryWrapper> m_categories;

        public HomePageViewModel(INavigationService navigationService)
            : base(navigationService)
        {
            m_repositories = new BindableCollection<RepositoryTileViewModel>();
            m_categories = new List<CategoryWrapper>();
            SaveNeeded = false;

            App.Current.Suspending += OnSuspending;
        }

        public bool SaveNeeded { get; set; }

        /// <summary>
        /// On Suspending, save changes if needed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        async void OnSuspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e)
        {
            if (SaveNeeded)
            {
                var operation = e.SuspendingOperation.GetDeferral();
                await SaveHomePage();
                operation.Complete();
                SaveNeeded = false;
            }
        }

        /// <summary>
        /// On Desactivate, save changes if needed
        /// </summary>
        /// <param name="close"></param>
        protected async override void OnDeactivate(bool close)
        {
            App.Current.Suspending -= OnSuspending;

            if (SaveNeeded)
            {
                await SaveHomePage();
                SaveNeeded = false;
            }
        }

        /// <summary>
        /// Initialize
        /// </summary>
        protected override async void OnInitialize()
        {
            Title = "MusicExplorer";

            m_repositories.Clear();
            var repositories = RepositoryBase.GetAllRepositories();
            foreach (var repository in repositories)
            {
                var wrapper = await RepositoryTileViewModel.CreateAsync(this, repository);
                m_repositories.Add(wrapper);
            }

            await RefreshGroups();

            HideLoading();
        }

        public event EventHandler UpdateGroupsEvent = delegate { };
        private async Task RefreshGroups()
        {
            m_categories.Clear();

            var categories = new List<Category>();
            if (Parameters.UseSampleData)
            {
                for(int i = 0; i < 3; i++)
                {
                    categories.Add(new Category(Guid.NewGuid()) { Order = i });

                    for (int j = 0; j < 5; j++)
                    {
                        var group = new QueryGroup(Guid.NewGuid());
                        if (j % 3 == 0)
                        {
                            group.Size = QueryGroupSize.Small;
                        }
                        else if (j % 2 == 0)
                        {
                            group.Size = QueryGroupSize.Medium;
                        }
                        else
                        {
                            group.Size = QueryGroupSize.Large;
                        }
                        group.CategoryId = categories[i].Id;
                        group.Order = j;
                        group.Name = i + " test " + j;
                        categories[i].Groups.Add(group);
                    }
                }
            }
            else
            {
                categories = await ServiceDatabase.GetAllCategoriesAsync();
            }
            foreach(var category in categories)
            {
                var categoryWrapper = new CategoryWrapper(this, category);
                foreach (var group in category.Groups)
                {
                    categoryWrapper.Groups.Add(await QueryGroupTileViewModel.CreateAsync(categoryWrapper, group));
                }
                m_categories.Add(categoryWrapper);
            }

            UpdateGroupsEvent(this, EventArgs.Empty);
        }

        public void NavigateToRepository(ItemClickEventArgs eventArgs)
        {
            var repository = (RepositoryTileViewModel)eventArgs.ClickedItem;

            m_navigationService.NavigateToViewModel<RepositoryPageViewModel>(new RepositoryPageNavigationObject()
                {
                    Root = Root,
                    SourcePage = this,
                    Repository = repository.Repository
                });
        }

        private async Task SaveHomePage()
        {
            var a = m_categories;

            var categories = new List<Category>();
            categories.AddRange(m_categories.Select(c => c.Category));
            for(int i = 0; i < categories.Count; i++)
            {
                var category = categories[i];
                category.Groups.AddRange(m_categories[i].Groups.Select(g => g.Group));
            }

            await ServiceDatabase.UpdateCategories(categories);
        }

        public void NavigateToTracks(ItemClickEventArgs eventArgs)
        {
            var group = (QueryGroupTileViewModel)eventArgs.ClickedItem;

            m_navigationService.NavigateToViewModel<TracksPageViewModel>(new TracksPageNavigationObject()
            {
                Root = Root,
                SourcePage = this,
                Group = group.Group
            });
        }

        public void AddGroup()
        {
            m_navigationService.NavigateToViewModel<GroupEditionViewModel>(new GroupEditionNavigationObject()
            {
                Root = Root,
                SourcePage = this,
                Group = new QueryGroup(Guid.NewGuid()) //{ DisplayNameOnHomeScreen = true }
            });
        }

        public void EditGroup()
        {
            m_navigationService.NavigateToViewModel<GroupEditionViewModel>(new GroupEditionNavigationObject()
            {
                Root = Root,
                SourcePage = this,
                Group = SelectedGroup.Group
            });
        }

        public void DeleteGroup()
        {
            SaveNeeded = true;
            var category = m_categories.First(g => g.Groups.Contains(m_selectedGroup));
            category.Groups.Remove(m_selectedGroup);
            if(ResetCategories()) UpdateGroupsEvent(this, EventArgs.Empty);
        }

        public void UpdateGroups(MusicExplorer.Common.BeforeDropItemsEventArgs e)
        {
            if(e.NewGroupIndex != e.OldGroupIndex || (e.NewIndex != e.OldIndex))
            {
                SaveNeeded = true;
            }

            if (e.RequestCreateNewGroup)
            {
                // 1. Create new group
                var category = new CategoryWrapper(this, new Category(Guid.NewGuid()) { Order = e.NewGroupIndex });
                m_categories.Insert(e.NewGroupIndex, category);

                // 2. Reasign datasource
                UpdateGroupsEvent(this, EventArgs.Empty);
            }
        }

        private bool ResetCategories()
        {
            bool needReset = false;
            for (int i = m_categories.Count - 1; i >= 0; i--)
            {
                if (m_categories[i].Groups.Count == 0 && m_categories.Count > 1)
                {
                    m_categories.RemoveAt(i);
                    needReset = true;
                }
            }
            return needReset;
        }

        public void RemoveEmptyCategory(DragEventArgs e)
        {
            if (ResetCategories())
            {
                UpdateGroupsEvent(this, EventArgs.Empty);
            }
        }

        public BindableCollection<RepositoryTileViewModel> Repositories { get { return m_repositories; } }
        public List<CategoryWrapper> GrouppedGroups { get { return m_categories; } }

        public override bool CanGoBack { get { return false; } }
        
        internal void RefreshSelectedGroup()
        {
            m_selectedGroup = m_categories.SelectMany(g => g.Groups).FirstOrDefault(g => g.IsSelected);
            NotifyOfPropertyChange(() => SelectedGroup);
        }

        private QueryGroupTileViewModel m_selectedGroup;
        public QueryGroupTileViewModel SelectedGroup { get { return m_selectedGroup; } }

        public void GoInPersonalizedMode()
        {
            InPersonalizedMode = !InPersonalizedMode;
        }

        public async void SetTileSize(MenuFlyoutItem item)
        {
            switch((string)item.Tag)
            {
                case "big":
                    SelectedGroup.Size = QueryGroupSize.Large;
                    break;
                case "wide":
                    SelectedGroup.Size = QueryGroupSize.Medium;
                    break;
                case "small":
                    SelectedGroup.Size = QueryGroupSize.Small;
                    break;
                default:
                    throw new NotSupportedException();
            }

            await SelectedGroup.ReloadImage();

            UpdateGroupsEvent(this, EventArgs.Empty);
        }

        private bool m_inPersonalizedMode;
        public bool InPersonalizedMode
        {
            get { return m_inPersonalizedMode; }
            set
            {
                if (m_inPersonalizedMode != value)
                {
                    m_inPersonalizedMode = value;
                    NotifyOfPropertyChange(() => InPersonalizedMode);
                }
            }
        }


        public override string CompleteTitle
        {
            get
            {
                return Title;
            }
        }
    }
}
